package com.boyadegroot.divelog.ui.diver;

import android.annotation.TargetApi;
import android.app.Activity;
import android.app.DatePickerDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.SQLException;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.boyadegroot.divelog.R;
import com.boyadegroot.divelog.data.DiveLogData;
import com.boyadegroot.divelog.models.DiveCertification;
import com.boyadegroot.divelog.models.Diver;
import com.boyadegroot.divelog.utilities.DateUtils;

import java.util.Calendar;
import java.util.Date;

public class DiverEdit extends ActionBarActivity implements DatePickerDialog.OnDateSetListener {

    private static final String TAG = DiverEdit.class.getName();
    
    public static final String IN_DIVER = "diver";
    public static final String OUT_DIVER = "diver";

    private long mDiverId;

    private EditText mUsername;
    private EditText mFirstName;
    private EditText mLastName;
    private EditText mBirthDate;
    private EditText mCertification;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // Log.v(TAG, "onCreate(Bundle savedInstanceState)");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.fragment_diver_edit);
        getViewElements();
        Diver diver = getIntent().getParcelableExtra("diver");
        createView(diver);
    }

    public void onSaveDiverClick(MenuItem item) {
        DiveLogData data = DiveLogData.getInstance(getApplicationContext());
        String username = mUsername.getText().toString();
        String firstname = mFirstName.getText().toString();
        String lastname = mLastName.getText().toString();
        Long birthdate = (long) mBirthDate.getTag();
        Long certification_id = (long) mCertification.getTag();
        Toast toast = null;
        try {
            // Log.d(TAG, "Updating diver with id = " + mDiverId);
            if (data.updateDiver(mDiverId, username, firstname, lastname, birthdate, certification_id)) {
                // Log.d(TAG, "Diver with id = " + mDiverId + " updated successfully");
                Intent intentData = new Intent();
                intentData.putExtra("diverId", mDiverId);
                setResult(Activity.RESULT_OK, intentData);
                finish();
            } else {
                Log.e(TAG, "Error updating diver with id = " + mDiverId);
                toast = Toast.makeText(this, R.string.error_editdiver_save, Toast.LENGTH_SHORT);
            }
        } catch (SQLException e) {
            Log.e(TAG, "SQLException updating diver with id = " + mDiverId + ": " + e.getMessage());
            toast = Toast.makeText(this, R.string.error_editdiver_save, Toast.LENGTH_SHORT);
        }
        if (toast != null) {
            toast.setGravity(Gravity.TOP, 0, 150);
            toast.show();
        }
    }

    public void onBirthDateClick(View v) {
        openBirthdatePicker();
    }

    private void openBirthdatePicker() {
        DatePickerDialogFragment birthdatePicker = new DatePickerDialogFragment();
        birthdatePicker.setPastOnly();
        birthdatePicker.show(getFragmentManager(), "birthdatePicker");
    }

    private final TextWatcher fieldsWatcher = new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {
        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {
        }

        @Override
        public void afterTextChanged(Editable editable) {
            updateSaveButton();
        }
    };

    private void updateSaveButton() {
        invalidateOptionsMenu();
    }

    @Override
    public void onDateSet(DatePicker view, int year, int month, int date) {
        EditText birthdate = (EditText) findViewById(R.id.birthdate);
        birthdate.setText(DateUtils.getLongDateString(year, month, date));
        birthdate.setTag(DateUtils.getTimestamp(year, month, date));
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_diveredit, menu);
        MenuItem save = menu.findItem(R.id.menuitem_save);
        boolean mandatoryEmpty = (
            mUsername.getText().toString().trim().equals("")
        );
        save.setEnabled(!mandatoryEmpty);
        return true;
    }

    private void createView(Diver diver) {
        Log.d(TAG, "createView(diver = " + diver + ")");
        if (diver == null) {
            throw new Error("Diver is null");
        }
        mDiverId = diver.getId();
        mUsername.setText(diver.getUsername());
        mFirstName.setText(diver.getFirstName());
        mLastName.setText(diver.getLastName());
        Long birthDate = diver.getBirthDate();
        if (birthDate != 0) {
            mBirthDate.setText(DateUtils.getLongDateString(birthDate));
            mBirthDate.setTag(birthDate);
        }
        DiveCertification certification = diver.getCertification();
        if (certification != null) {
            long certificationId = certification.getId();
            String certificationName = certification.getName();
            mCertification.setText(certificationName);
            mCertification.setTag(certificationId);
        }
    }

    private void getViewElements() {
        mUsername = (EditText) findViewById(R.id.username);
        mFirstName = (EditText) findViewById(R.id.firstname);
        mLastName = (EditText) findViewById(R.id.lastname);
        mBirthDate = (EditText) findViewById(R.id.birthdate);
        mCertification = (EditText) findViewById(R.id.certification);
        mFirstName.addTextChangedListener(fieldsWatcher);
        mLastName.addTextChangedListener(fieldsWatcher);
        mBirthDate.addTextChangedListener(fieldsWatcher);
        mCertification.addTextChangedListener(fieldsWatcher);
        mLastName.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                boolean handled = false;
                if (actionId == EditorInfo.IME_ACTION_NEXT) {
                    openBirthdatePicker();
                    handled = true;
                }
                return handled;
            }
        });
        // TODO: Add chooser to choose certification
    }

    public static class DatePickerDialogFragment extends DialogFragment {

        public static final String YEAR = "Year";
        public static final String MONTH = "Month";
        public static final String DATE = "Day";

        private DatePicker _datePicker;
        private DatePickerDialog.OnDateSetListener _listener;
        private long _maxDate;

        @Override
        public void onAttach(Activity activity) {
            super.onAttach(activity);
            this._listener = (DatePickerDialog.OnDateSetListener) activity;
        }

        @Override
        public void onDetach() {
            this._listener = null;
            super.onDetach();
        }

        @TargetApi(11)
        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            Bundle b = getArguments();
            if (b == null) { // If no date was set, default to current date
                b = new Bundle();
                Calendar today = Calendar.getInstance();
                b.putInt(DatePickerDialogFragment.YEAR, today.get(Calendar.YEAR));
                b.putInt(DatePickerDialogFragment.MONTH, today.get(Calendar.MONTH));
                b.putInt(DatePickerDialogFragment.DATE, today.get(Calendar.DAY_OF_MONTH));
            }
            int year = b.getInt(YEAR);
            int month = b.getInt(MONTH);
            int date = b.getInt(DATE);

            // Jelly Bean introduced a bug in DatePickerDialog (and possibly
            // TimePickerDialog as well), and one of the possible solutions is
            // to postpone the creation of both the listener and the BUTTON_* .
            //
            // Passing a null here won't harm because DatePickerDialog checks for a null
            // whenever it reads the listener that was passed here. >>> This seems to be
            // true down to 1.5 / API 3, up to 4.1.1 / API 16. <<< No worries. For now.
            //
            // See my own question and answer, and details I included for the issue:
            //
            // http://stackoverflow.com/a/11493752/489607
            // http://code.google.com/p/android/issues/detail?id=34833
            //
            // Of course, suggestions welcome.

            final DatePickerDialog pickerDialog = new DatePickerDialog(getActivity(), getConstructorListener(), year, month, date);

            _datePicker = pickerDialog.getDatePicker();
            if (_maxDate != 0) {
                _datePicker.setMaxDate(_maxDate);
            }

            if (hasJellyBeanAndAbove()) {
                pickerDialog.setButton(
                    DialogInterface.BUTTON_POSITIVE,
                    getActivity().getString(android.R.string.ok),
                    new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            _listener.onDateSet(
                                    _datePicker,
                                    _datePicker.getYear(),
                                    _datePicker.getMonth(),
                                    _datePicker.getDayOfMonth()
                            );
                        }
                    })
                ;
                pickerDialog.setButton(
                    DialogInterface.BUTTON_NEGATIVE,
                    getActivity().getString(android.R.string.cancel),
                    new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                        }
                    }
                );
            }
            return pickerDialog;
        }

        public void setPastOnly() {
            setMaxDate(new Date().getTime());
        }

        public void setMaxDate(long maxDate) {
            _maxDate = maxDate;
        }

        private boolean hasJellyBeanAndAbove() {
            return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
        }

        private DatePickerDialog.OnDateSetListener getConstructorListener() {
            return hasJellyBeanAndAbove() ? null : _listener;
        }
    }

}
